package com.gopay.common.user.manager.impl;

import com.gopay.common.constants.microdone.EnumMicroScene;
import com.gopay.common.constants.microdone.PwdCtrlFingerKeyConstants;
import com.gopay.common.constants.microdone.PwdCtrlFingerUserStatConstants;
import com.gopay.common.domain.user.PwdCtrlFingerReqDO;
import com.gopay.common.domain.user.PwdCtrlFingerUserInfo;
import com.gopay.common.user.dao.PwdCtrlFingerUserInfoDAO;
import com.gopay.common.user.manager.PwdCtrlFingerUserInfoManager;
import com.gopay.common.util.RequestUtils;
import com.gopay.common.util.pwd.PwdCtrlFingerUtil;
import com.gopay.common.vo.PwdCtrlFingerVerifyResultVO;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author yu_liu6@hnair.com
 * @date 2018-05-22 17:17:26
 */
@Component(value = "pwdCtrlFingerUserInfoManager")
public class PwdCtrlFingerUserInfoManagerImpl implements PwdCtrlFingerUserInfoManager {
    /** logger */
    private static final Logger LOGGER = LoggerFactory.getLogger(PwdCtrlFingerUserInfoManagerImpl.class);

    @Autowired
    private PwdCtrlFingerUserInfoDAO pwdCtrlFingerUserInfoDAO;

    @Override
    public PwdCtrlFingerUserInfo findByUserName(String userName) {
        String hql = "from PwdCtrlFingerUserInfo where userName = :userName";
        Map<String, Object> param = new HashMap<>(2);
        param.put("userName", userName);
        List<PwdCtrlFingerUserInfo> resultList = pwdCtrlFingerUserInfoDAO.findByHql(hql, param);
        return resultList.isEmpty() ? null : resultList.get(0);
    }

    @Override
    public void save(PwdCtrlFingerUserInfo info) {
        info.setCreatedTs(new Date());
        info.setLastUpdTs(new Date());
        pwdCtrlFingerUserInfoDAO.save(info);
    }

    @Override
    public void updateSelective(PwdCtrlFingerUserInfo info) {
        info.setLastUpdTs(new Date());
        pwdCtrlFingerUserInfoDAO.update(info);
    }

    @Override
    public PwdCtrlFingerVerifyResultVO fingerAuth(HttpServletRequest request, String userName,
                                                  String authUrl, EnumMicroScene operResource) {
        try {
            if(verifyFingerParam(request, userName, authUrl, operResource)){
                Map<String, String> param = new HashMap<>(16);
                param.put("apps_id", operResource.getCode());
                param.put("app_type", "1");
                param.put("user_name", userName);
                param.put("pwdResultHash", request.getParameter("pwdResultHash"));
                param.put("random_num", request.getAttribute("mcrypt_key").toString());
                param.put("user_finger", request.getParameter("user_finger"));
                param.put("user_info", request.getParameter("hardList"));
                param.put("user_ip", RequestUtils.getRemoteRealIpAddr(request));
                PwdCtrlFingerVerifyResultVO resultVO = doFingerAuth(authUrl, param);
                request.setAttribute(PwdCtrlFingerKeyConstants.FINGER_AUTH_RESULT, resultVO);
                return resultVO;
            }
        } catch (Exception e) {
            LOGGER.error("【键盘芭蕾-支付按键信息采集】失败", e);
        }
        return null;
    }

    @Override
    public PwdCtrlFingerVerifyResultVO fingerLogin(PwdCtrlFingerReqDO reqDO) {
        try {
            if(verifyFingerVO(reqDO)){
                Map<String, String> param = new HashMap<>(16);
                param.put("apps_id", reqDO.getAppsId());
                param.put("app_type", "1");
                param.put("user_name", reqDO.getUserName());
                param.put("pwdResultHash", reqDO.getPwdResultHash());
                param.put("random_num", reqDO.getMcrptKey());
                param.put("user_finger", reqDO.getFinger());
                param.put("user_info", reqDO.getHardList());
                param.put("user_ip", reqDO.getIp());
                return doFingerAuth(reqDO.getAuthUrl(), param);
            }
        } catch (Exception e) {
            LOGGER.error("【键盘芭蕾-登录按键信息采集】失败", e);
        }
        return null;
    }

    private boolean verifyFingerParam(HttpServletRequest request, String userName,
                                      String authUrl, EnumMicroScene operResource){
        if(null == request){
            LOGGER.error("【键盘芭蕾】信息采集异常----->请求为空");
            return false;
        }
        if(StringUtils.isBlank(userName)){
            LOGGER.error("【键盘芭蕾】信息采集异常----->用户名为空");
            return false;
        }
        if(StringUtils.isBlank(authUrl)){
            LOGGER.error("【键盘芭蕾】信息采集异常----->认证服务器url为空");
            return false;
        }
        if(null == operResource){
            LOGGER.error("【键盘芭蕾】信息采集异常----->密码控件使用场景为空");
            return false;
        }
        if(StringUtils.isBlank(request.getParameter("pwdResultHash"))){
            LOGGER.error("【键盘芭蕾】信息采集异常----->密码hash值pwdResultHash为空");
            return false;
        }
        if(StringUtils.isBlank(request.getAttribute("mcrypt_key") + "")){
            LOGGER.error("【键盘芭蕾】信息采集异常----->随机因子mcrypt_key为空");
            return false;
        }
        if(StringUtils.isBlank(request.getParameter("user_finger"))){
            LOGGER.error("【键盘芭蕾】信息采集异常----->按键采集信息user_finger为空");
            return false;
        }
        if(StringUtils.isBlank(request.getParameter("hardList"))){
            LOGGER.error("【键盘芭蕾】信息采集异常----->硬件信息列表hardList为空");
            return false;
        }
        if(StringUtils.isBlank(RequestUtils.getRemoteRealIpAddr(request))){
            LOGGER.error("【键盘芭蕾】信息采集异常----->用户IP地址为空");
            return false;
        }
        return true;
    }

    private boolean verifyFingerVO(PwdCtrlFingerReqDO reqDO){
        if(null == reqDO){
            LOGGER.error("【键盘芭蕾】信息采集异常----->请求为空");
            return false;
        }
        if(StringUtils.isBlank(reqDO.getUserName())){
            LOGGER.error("【键盘芭蕾】信息采集异常----->用户名为空");
            return false;
        }
        if(StringUtils.isBlank(reqDO.getAuthUrl())){
            LOGGER.error("【键盘芭蕾】信息采集异常----->认证服务器url为空");
            return false;
        }
        if(StringUtils.isBlank(reqDO.getAppsId())){
            LOGGER.error("【键盘芭蕾】信息采集异常----->密码控件使用场景为空");
            return false;
        }
        if(StringUtils.isBlank(reqDO.getPwdResultHash())){
            LOGGER.error("【键盘芭蕾】信息采集异常----->密码hash值pwdResultHash为空");
            return false;
        }
        if(StringUtils.isBlank(reqDO.getMcrptKey())){
            LOGGER.error("【键盘芭蕾】信息采集异常----->随机因子mcrypt_key为空");
            return false;
        }
        if(StringUtils.isBlank(reqDO.getFinger())){
            LOGGER.error("【键盘芭蕾】信息采集异常----->按键采集信息user_finger为空");
            return false;
        }
        if(StringUtils.isBlank(reqDO.getHardList())){
            LOGGER.error("【键盘芭蕾】信息采集异常----->硬件信息列表hardList为空");
            return false;
        }
        if(StringUtils.isBlank(reqDO.getIp())){
            LOGGER.error("【键盘芭蕾】信息采集异常----->用户IP地址为空");
            return false;
        }
        return true;
    }

    private PwdCtrlFingerVerifyResultVO doFingerAuth(String authUrl, Map<String, String> param){
        String userName = param.get("user_name");
        PwdCtrlFingerUserInfo old = findByUserName(userName);
        PwdCtrlFingerVerifyResultVO resultVO = null;
        if(null == old){
            PwdCtrlFingerUserInfo info = new PwdCtrlFingerUserInfo();
            info.setUserName(userName);
            info.setStatus(PwdCtrlFingerUserStatConstants.MODELING);
            save(info);
            old = info;
            resultVO = PwdCtrlFingerUtil.registFinger(authUrl, param);
        } else if (PwdCtrlFingerUserStatConstants.TO_CANCEL.equals(old.getStatus())) {
            if(PwdCtrlFingerUtil.resetUserInfo(authUrl, userName)){
                old.setStatus(PwdCtrlFingerUserStatConstants.MODELING);
                updateSelective(old);
                resultVO = PwdCtrlFingerUtil.registFinger(authUrl, param);
            }
        } else if (PwdCtrlFingerUserStatConstants.SUCCESS.equals(old.getStatus())){
            resultVO = PwdCtrlFingerUtil.verifyFinger(authUrl, param);
        } else {
            resultVO = PwdCtrlFingerUtil.registFinger(authUrl, param);
        }
        if(null != resultVO){
            if(resultVO.isRegSuccess()){
                old.setStatus(PwdCtrlFingerUserStatConstants.SUCCESS);
                updateSelective(old);
            } else if (!resultVO.isRegSuccess() && !resultVO.isVerifySuccess()){
                //注册接口返回2的，即建模失败，需要清空数据
                if(!PwdCtrlFingerUtil.resetUserInfo(authUrl, userName)){
                    //如果重置用户习惯失败，需要在数据库标记，以便下次重发请求
                    old.setStatus(PwdCtrlFingerUserStatConstants.TO_CANCEL);
                    updateSelective(old);
                }
            }
        }
        return resultVO;
    }
}
